# coding=utf-8
from genericpath import getsize
import os
import Image
from django.core.files.uploadedfile import UploadedFile
from django.db import models
from com.kjssoft.common.file.models import AbstractCommonFile, FileContentType
from com.kjssoft.common.globals import DBTableAssist
from com.kjssoft.common.models import ServiceException
from com.kjssoft.rainbow import LOGGER
from settings.settings import PROJECT_ROOT_PATH

__author__ = 'Sea'

class RainbowImageModelServiceException(ServiceException):
    pass

class RainbowImageManager(models.Manager):
    COMMON_IMAGE_MODE = 'RGBA'
    COMMON_IMAGE_EXT = 'jpeg'

    def _format_image(self, image_file, image_file_name):
        if image_file.mode != self.COMMON_IMAGE_MODE:
            formatted_image = image_file.convert(self.COMMON_IMAGE_MODE)
            formatted_image.save(
                os.path.join(os.path.dirname(image_file.filename),
                    '%s.%s' % (image_file_name, self.COMMON_IMAGE_EXT)), self.COMMON_IMAGE_EXT.upper()
            )

    def create(self, uploadedFile, **kwargs):
        if uploadedFile and isinstance(uploadedFile, UploadedFile):
            if 'content_md5' in dir(uploadedFile):
                file_md5 = getattr(uploadedFile, 'content_md5')
                images = self.filter(uuid = file_md5)
                if images.count():
                    image_model = images[0]
                else:
                    original_out_put = os.path.join(RainbowImage.OUT_PUT_DIR, RainbowImage.ORIGINAL_OUT_PUT_DIR)
                    original_file_path = os.path.join(original_out_put, file_md5)
                    if not os.path.exists(original_file_path) or not os.path.isfile(original_file_path):
                        original_image = open(original_file_path, 'wb')
                        try:
                            if uploadedFile.multiple_chunks():
                                for chunk in uploadedFile.chunks():
                                    original_image.write(chunk)
                            else:
                                original_image.write(uploadedFile.read())
                        finally:
                            if original_image:
                                original_image.close()
                    img = Image.open(original_file_path)
                    self._format_image(img, file_md5)
                    LOGGER.debug('image content type %s' % img.format.upper())
                    image_model = super(RainbowImageManager, self).create(
                        uuid         = file_md5,
                        width        = img.size[0],
                        height        = img.size[1],
                        size = getsize(original_file_path),
                        name = file_md5,
                        content_type = FileContentType.objects.get(name = img.format.upper())
                    )
                    image_model.save()
                return image_model
        raise RainbowImageModelServiceException(111, 'aaa')

class RainbowImage(AbstractCommonFile):
    OUT_PUT_DIR = os.path.join(PROJECT_ROOT_PATH, 'static/rainbow/images')
    ORIGINAL_OUT_PUT_DIR = '0'

    width  = models.IntegerField()
    height = models.IntegerField()

    objects = RainbowImageManager()

    def resize(self, sizes):
        image_width  = self.width
        image_height = self.height
        original_out_put = os.path.join(RainbowImage.OUT_PUT_DIR, RainbowImage.ORIGINAL_OUT_PUT_DIR)
        image = Image.open(os.path.join(original_out_put, '%s.%s' % (self.uuid, RainbowImageManager.COMMON_IMAGE_EXT)))
        if isinstance(sizes, int):
            sizes = [sizes]
        for size in sizes:
            resize_out_put_path = os.path.join(RainbowImage.OUT_PUT_DIR, str(size))
            if not os.path.exists(resize_out_put_path):
                os.makedirs(resize_out_put_path)
            resize_image_file = os.path.join(resize_out_put_path, '%s.%s' % (self.uuid, RainbowImageManager.COMMON_IMAGE_EXT))
            if not os.path.exists(resize_image_file) or not os.path.isfile(resize_image_file):
                resize_width = size
                resize_height = int(size * image_height / image_width)
                resize_image = image.resize((resize_width, resize_height), Image.ANTIALIAS)
                resize_image.save(os.path.join(resize_out_put_path, '%s.%s' % (self.uuid, RainbowImageManager.COMMON_IMAGE_EXT)), RainbowImageManager.COMMON_IMAGE_EXT.upper())

    def __unicode__(self):
        return 'rainbow image %s (%s * %s), %s' % (
            self.uuid, self.width, self.height, self.content_type.name
        )

    class Meta:
        db_table = DBTableAssist.get_db_table_name('rainbow_image')
